home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Aminet 1 (Walnut Creek)
/
Aminet - June 1993 [Walnut Creek].iso
/
usenet
/
sources
/
volume89
/
languags
/
a68k242.3
< prev
next >
Wrap
Text File
|
1989-03-08
|
65KB
|
2,191 lines
Path: xanth!ukma!tut.cis.ohio-state.edu!mailrus!bbn!ulowell!page
From: page@swan.ulowell.edu (Bob Page)
Newsgroups: comp.sources.amiga
Subject: v89i025: a68k - 68000 assembler v2.42, Part03/04
Message-ID: <12036@swan.ulowell.edu>
Date: 8 Mar 89 01:49:32 GMT
Organization: University of Lowell, Computer Science Dept.
Lines: 2180
Approved: page@swan.ulowell.edu
Submitted-by: jlydiatt@jlami.wimsey.bc.ca (Jeff Lydiatt)
Posting-number: Volume 89, Issue 25
Archive-name: languages/a68k242.3
# This is a shell archive.
# Remove everything above and including the cut line.
# Then run the rest of the file through sh.
#----cut here-----cut here-----cut here-----cut here----#
#!/bin/sh
# shar: Shell Archiver
# Run the following text with /bin/sh to create:
# A68kdef.h
# Adirect.c
# Codegen.c
# Opcodes.c
# This archive created: Tue Mar 7 20:42:01 1989
cat << \SHAR_EOF > A68kdef.h
/*------------------------------------------------------------------*/
/* */
/* MC68000 Cross Assembler */
/* */
/* Copyright (c) 1985 by Brian R. Anderson */
/* */
/* #define statements - January 6, 1989 */
/* */
/* This program may be copied for personal, non-commercial use */
/* only, provided that the above copyright notice is included */
/* on all copies of the source code. Copying for any other use */
/* without the consent of the author is prohibited. */
/* */
/*------------------------------------------------------------------*/
/* */
/* Originally published (in Modula-2) in */
/* Dr. Dobb's Journal, April, May, and June 1986. */
/* */
/* AmigaDOS conversion copyright 1989 by Charlie Gibbs. */
/* */
/*------------------------------------------------------------------*/
#ifdef AZTEC_C
#include <ctype.h>
#endif
extern char *malloc();
extern int open(), creat(), read(), write(), close(), unlink();
extern long lseek();
#define TRUE 1
#define FALSE 0
#define NODEF 32767 /* High line number for undefined symbols */
/* Assembler configuration parameters */
#define MAXLINE 128 /* Longest source line */
#define MAXFN 41 /* Maximum length of file name */
#define MAXSREC 16 /* Maximum S-record data length */
#define MAXREF 4 /* Number of line numbers in reference entry */
#define DEFHASH 2047 /* Default number of elements in hash table */
#define DEFHEAP2 1024 /* Default size for secondary heap */
#define INCSKSIZ 2048 /* Size of INCLUDE skip table */
#ifdef MSDOS
#define CHUNKSIZE 2048 /* Memory chunks for Itty Bitty Memories */
#else
#define CHUNKSIZE 8192 /* Size of memory chunks allocated for tables */
#endif
#define BUFFSIZE 2048 /* File buffer size */
#define ObjMAX 32 /* Max. hex object code digits in listing */
/* Hunk number definitions */
#define HunkNone 0 /* Not in a hunk */
#define HunkUnit 999
#define HunkName 1000
#define HunkCode 1001
#define HunkData 1002
#define HunkBSS 1003
#define HunkR32 1004
#define HunkR16 1005
#define HunkR8 1006
#define HunkExt 1007
#define HunkSym 1008
#define HunkDbg 1009
#define HunkEnd 1010
#define MEMF_FAST 0x80000000L /* Hunk must load in FAST memory */
#define MEMF_CHIP 0x40000000L /* Hunk must load in CHIP memory */
/* Hunk numbers denoting special symbol attributes */
#define ABSHUNK 32767 /* Absolute */
/* Addressing mode flag values */
#define DReg 1 /* Data Register */
#define ARDir 2 /* Address Register Direct */
#define ARInd 3 /* Address Register Indirect */
#define ARPost 4 /* Address Register with Post-Increment */
#define ARPre 5 /* Address Register with Pre-Decrement */
#define ARDisp 6 /* Address Register with Displacement */
#define ARDisX 7 /* Address Register with Disp. & Index */
#define AbsW 8 /* Absolute Short (16-bit Address) */
#define AbsL 9 /* Absolute Long (32-bit Address) */
#define PCDisp 10 /* Program Counter Relative, with Displacement */
#define PCDisX 11 /* Program Counter Relative, with Disp. & Index */
#define Imm 12 /* Immediate */
#define MultiM 13 /* Multiple Register Move */
#define SR 14 /* Status Register */
#define CCR 15 /* Condition Code Register */
#define USP 16 /* User's Stack Pointer */
#define Null 0 /* Error Condition, or Operand missing */
#define X0 0 /* Register types */
#define Dreg 1
#define Areg 2
#define S0 0 /* Size types */
#define Byte 1
#define Word 2
#define S3 3
#define Long 4
#define CMPM 0xB108
#define JMP 0x4EC0
#define JSR 0x4E80
#define LEA 0x41C0
#define LINK 0x4E50
#define NOP 0x4E71
#define PEA 0x4840
#define STOP 0x4E72
#define SWAP 0x4840
#define UNLK 0x4E58
#define None 0 /* Assembler directives */
#define Org 1
#define DC 2
#define DS 3
#define Even 4
#define End 5
#define Cnop 6
#define Section 7
#define CSeg 8
#define DSeg 9
#define BSS 10
#define Idnt 11
#define DCB 12
#define Near 13
#define Far 14
#define BadMac 15
#define SkipDir 16 /* Skippable INCLUDE directives start here */
#define Equ 16
#define Public 17
#define Xdef 18
#define Xref 19
#define Page 20
#define DoList 21
#define NoList 22
#define Space 23
#define Title 24
#define Include 25
#define Set 26
#define Macro 27
#define IfEQ 28
#define IfNE 29
#define IfGT 30
#define IfGE 31
#define IfLT 32
#define IfLE 33
#define IfC 34
#define IfNC 35
#define IfD 36
#define IfND 37
#define EndC 38
#define Equr 39
#define Reg 40
#define MacCall 41
/* BITSETs of the modes MISSING from effective address modes */
#define ea 0x0000 /* Effective addressing - all modes */
#define dea 0x0002 /* Data effective addressing */
#define mea 0x0003 /* Memory effective addressing */
#define cea 0x081B /* Control effective addressing */
#define aea 0x0E00 /* Alterable effective addressing */
#define xxx 0xE000 /* extra modes: CCR/SR/USP */
#define IN & /* Simulated BITSET test */
/* AdrModeA bit definitions */
#define RegMem3 0x0001 /* 0 = register, 1 = memory */
#define Ry02 0x0002 /* Register Rx - bits 0-2 */
#define Rx911 0x0004 /* Register Ry - bits 9-11 */
#define Data911 0x0008 /* Immediate data - bits 9-11 */
#define CntR911 0x0010 /* Count register or immediate data */
#define Brnch 0x0020 /* Relative branch */
#define DecBr 0x0040 /* Decrement and branch */
#define Data03 0x0080 /* TRAP vector in 0-3 */
#define Data07 0x0100 /* Data in 0-7 (MOVEQ) */
#define OpM68D 0x0200 /* Data register in 6-8 */
#define OpM68A 0x0400 /* Address register in 6-8 (ADDA/CMPA/SUBA) */
#define OpM68C 0x0800 /* CMP (Compare) */
#define OpM68X 0x1000 /* EOR (Exclusive or) */
#define OpM68S 0x2000 /* EXT (Sign extension) */
#define OpM68R 0x4000 /* MOVEP (Register/memory) */
#define OpM37 0x8000 /* EXG (Exchange registers) */
#define TwoOpsA 0xDF4D /* Two operands are required */
/* AdrModeB bit definitions */
#define Bit811 0x0001 /* Bit operations - bits 8-11 as switch */
#define Size67 0x0002 /* 00 = byte, 01 = word, 10 = long */
#define Size6 0x0004 /* 0 = word, 1 = long */
#define Sz1213A 0x0008 /* 01 = byte, 11 = word, 10 = long */
#define Sz1213 0x0010 /* 11 = word, 10 = long */
#define Exten 0x0020 /* Opcode extension is required */
#define EA05a 0x0040 /* Effective address - all */
#define EA05b 0x0080 /* All except ARDir */
#define EA05c 0x0100 /* All except ARDIR and Imm */
#define EA05d 0x0200 /* All except PCDisp, PCDisx, and Imm */
#define EA05e 0x0400 /* All except ARDir, PCDisp, PCDisx, and Imm */
#define EA05f 0x0800 /* All except Dreg, ARDir, ARPost, ARPre, Imm */
#define EA05x 0x1000 /* Dual mode - AND/OR */
#define EA05y 0x2000 /* Dual mode - ADD/SUB */
#define EA05z 0x4000 /* Dual mode - MOVEM */
#define EA611 0x8000 /* Eff. Adr. in 6-11 (used only by MOVE) */
#define TwoOpsB 0xF3DD /* Two operands are required */
#define ImmMode 0x0422 /* Immediate instructions */
#define SrcPC 0xF8C0 /* Source operand may be PCDisp */
#define Dummy 0 /* Error codes */
#define AlignErr 1
#define NoCode 2
#define SymDup 3
#define Undef 4
#define ModeErr 5
#define OperErr 6
#define BraErr 7
#define AddrErr 8
#define SizeErr 9
#define EndErr 10
#define AbsReq 11
#define RelErr 12
#define NoIncl 13
#define FwdRef 14
#define NotSFmt 15
#define NeedLab 16
#define Phase 17
#define NoENDM 18
#define NoENDC 19
#define ManyENDC 20
#define DCOflo 21
#define ManySect 22
#define DupMac 23
#define MultLab 24
#define NoStrEnd 25
#define BccSDsp0 26
#define ERRMAX 10 /* Size of error message table */
SHAR_EOF
cat << \SHAR_EOF > Adirect.c
/*------------------------------------------------------------------*/
/* */
/* MC68000 Cross Assembler */
/* */
/* Copyright (c) 1985 by Brian R. Anderson */
/* */
/* Assembler directive processing - January 6, 1989 */
/* */
/* This program may be copied for personal, non-commercial use */
/* only, provided that the above copyright notice is included */
/* on all copies of the source code. Copying for any other use */
/* without the consent of the author is prohibited. */
/* */
/*------------------------------------------------------------------*/
/* */
/* Originally published (in Modula-2) in */
/* Dr. Dobb's Journal, April, May, and June 1986. */
/* */
/* AmigaDOS conversion copyright 1989 by Charlie Gibbs. */
/* */
/*------------------------------------------------------------------*/
#include <stdio.h>
#include "a68kdef.h"
#include "a68kglb.h"
/* Functions */
extern int LineParts(), Instructions();
extern int GetInstModeSize(), GetMultReg(), CountNest();
extern int ReadSymTab(), GetArgs(), GetAReg(), OpenIncl();
extern long AddrBndW(), AddrBndL(), GetValue(), CalcValue();
extern char *AddName(), *GetField();
extern struct SymTab *NextSym();
extern struct SymTab **HashIt();
int ObjDir (dummy) int dummy;
/* Generates Object Code for Assembler Directives */
{
register char *s, *t;
register int i, j;
int oploc;
long templong;
char tempop[MAXLINE], delim;
struct SetFixup *sf;
switch (Dir) {
case Org: /* ORG */
PrntAddr = MakeHunk = TRUE;
templong = GetValue (SrcOp, SrcLoc);
if (DefLine2 >= LineCount) {
Error (SrcLoc, FwdRef); /* Illegal forward reference */
break;
}
if (OpCode[0] == 'R') { /* RORG */
if (Hunk2 != ABSHUNK) {
Error (SrcLoc, RelErr); /* RORG needs absolute value */
break;
}
} else if (Hunk2 != CurrHunk) {
Error (SrcLoc, RelErr); /* Can't ORG out of hunk */
break;
}
if ((!Pass2 || (HunkType == HunkBSS))
&& (templong < AddrCnt) /* If we're ORGing to a lower address */
&& (AddrCnt > OrgHigh)) /* and this is the highest we've been */
OrgHigh = AddrCnt; /* remember how far we got. */
AddrCnt = templong; /* Update the location counter */
OrgFlag = TRUE; /* Indicate object fixups are needed */
break;
case Equ: /* EQU */
if (Label[0] == '\0')
Error (0, NeedLab); /* Need a label */
ObjSrc = GetValue (SrcOp, SrcLoc);
if (DefLine2 >= LineCount)
Error (SrcLoc, FwdRef); /* Illegal forward reference */
Src.Hunk = Hunk2;
PrntAddr = MakeHunk = TRUE;
break;
case DC: /* DC */
if ((Size == Word) || (Size == Long))
AddrCnt = AddrBndW (AddrCnt);
s = Line + SrcLoc;
while (!isspace(*s) && (*s != '\0') && (*s != ';')) {
oploc = s - Line;
if (((*s == '\'') || (*s == '"')) /* String */
&& (Size == Byte)) {
delim = *s++; /* Get the delimiter */
while (1) {
if (*s == '\0') { /* No closing delimiter */
Error (s-Line, NoStrEnd);
break;
}
if (*s == delim) { /* End of string? */
if (*(++s) != delim) /* Check next character */
break; /* End of string */
} /* Otherwise it's an apostrophe in the string */
Src.Hunk = ABSHUNK; /* Absolute value */
ObjString[nX++] = *s++; /* Current character */
}
} else { /* Not a string constant */
s = GetField (s, SrcOp);
ObjSrc = GetValue (SrcOp, oploc); /* Value */
if ((Src.Hunk = Hunk2) != ABSHUNK) { /* Hunk no. */
templong = AddrCnt + nX; /* Relocatable */
PutRel (templong, Hunk2, Size);
}
if (Size == 4) {
ObjString[nX++] = (ObjSrc >> 24) & 0x00FF;
ObjString[nX++] = (ObjSrc >> 16) & 0x00FF;
}
if (Size >= 2)
ObjString[nX++] = (ObjSrc >> 8) & 0x00FF;
ObjString[nX++] = ObjSrc & 0x00FF;
if (Size == 2)
templong = 0xFFFF0000L;
else if (Size == 1)
templong = 0xFFFFFF00L;
if (Size < 4)
if (((ObjSrc & templong) != 0)
&& ((ObjSrc & templong) != templong))
Error (s-Line, SizeErr);
}
if (*s == ',')
s++; /* Skip over separator */
}
if (!isspace(*s) && (*s != '\0') && (*s != ';'))
Error (s-Line, OperErr); /* Didn't end properly */
AddrAdv = InstSize = nX;
PrntAddr = MakeHunk = TRUE;
break;
case DS: /* DS */
if (DestLoc != 0) {
Error (DestLoc, OperErr); /* Only one operand is allowed */
PrntAddr = MakeHunk = TRUE;
break;
}
AddrAdv = GetValue (SrcOp, SrcLoc);
if (DefLine2 >= LineCount) {
Error (SrcLoc, FwdRef); /* Illegal forward reference */
AddrAdv = 0;
}
if (Hunk2 != ABSHUNK)
Error (SrcLoc, AbsReq); /* Count must be absolute */
if (Size == Word) { /* Words */
AddrCnt = AddrBndW (AddrCnt);
AddrAdv <<= 1;
}
if (Size == Long) { /* Long words */
AddrCnt = AddrBndW (AddrCnt);
AddrAdv <<= 2;
}
if (Pass2 && (HunkType != HunkBSS)) { /* If this isn't */
templong = AddrAdv; /* a BSS hunk, */
while (templong >= 4) { /* generate zeros */
AppendSdata (0L, 4); /* to fill the area */
templong -= 4;
}
if (templong > 0) {
i = templong;
AppendSdata (0L, i);
}
}
PrntAddr = MakeHunk = TRUE;
break;
case Even: /* EVEN */
AddrCnt = AddrBndW (AddrCnt);
PrntAddr = MakeHunk = TRUE;
break;
case End: /* END */
if (Pass2)
if (SrcOp[0] != '\0')
EndAddr = GetValue (SrcOp, SrcLoc);
else
EndAddr = 0;
PrntAddr = MakeHunk = TRUE;
break;
case Xdef: /* XDEF */
case Public: /* PUBLIC */
if (SFormat)
Error (OpLoc, NotSFmt); /* Not in S-format */
s = Line + SrcLoc;
while (!isspace(*s) && (*s != '\0')) {
oploc = s - Line;
s = GetField (s, SrcOp); /* Get a symbol */
if (ReadSymTab (SrcOp)) {
if (!Pass2) {
if ((Sym->Flags & 0x61) == 0) {
Sym->Flags |= 2; /* Set XDEF flag */
if (OpCode[0] == 'P') {
Sym->Flags |= 0x80; /* Defined as PUBLIC */
}
}
} else {
if (Sym->Defn != LineCount) /* If not PUBLIC->XREF */
AddRef (LineCount); /* it's a reference */
if (Sym->Defn == NODEF)
Error (oploc, Undef); /* Never got defined */
else if (Sym->Flags & 0x60)
Error (oploc, AddrErr); /* Can't XDEF a register */
}
} else if (!Pass2) { /* Not yet defined */
if (OpCode[0] == 'P') { /* Treat PUBLIC as XREF */
AddSymTab (SrcOp, 0L, 0L ,LineCount, 0x81);
Sym->Hunk = ~((long) Sym->Nam);
} else {
AddSymTab (SrcOp, 0L, CurrHunk, NODEF, 2); /* XDEF */
}
}
if (*s == ',')
s++; /* Skip over separator */
}
break;
case Xref: /* XREF */
if (SFormat)
Error (OpLoc, NotSFmt); /* Not in S-format */
s = Line + SrcLoc;
while (!isspace(*s) && (*s != '\0')) {
oploc = s - Line;
s = GetField (s, SrcOp);
if (Pass2) {
if (ReadSymTab (SrcOp)) {
if (Sym->Defn != LineCount) {
AddRef (LineCount); /* Ignore extraneous XREF */
}
}
} else {
if (!ReadSymTab (SrcOp)) { /* Only if not defined */
AddSymTab (SrcOp, 0L, 0L, LineCount, 1);
Sym->Hunk = ~((long) Sym->Nam);
}
}
if (*s == ',')
s++; /* Skip over separator */
}
break;
case Page: /* PAGE */
if (Pass2 && (LineCount > 1)) /* Ignore PAGE at start of file */
LnCnt = LnMax; /* Resume on a new page */
break;
case DoList: /* LIST */
ListOff = FALSE;
if (!Pass2 && !SuppList && (IncStart != 0)) {
IncStart = 0; /* We can't */
if (SkipLim->Set1 != NULL) { /* skip this */
SetFixLim = SkipLim->Set1; /* INCLUDE file */
SetFixLim++; /* in pass 2 */
} /* (we must */
} /* list it). */
break;
case NoList: /* NOLIST */
ListOff = TRUE;
break;
case Space: /* SPC */
if (Pass2 && !ListOff && !SuppList) {
if (SrcOp[0] != '\0')
j = GetValue (SrcOp, SrcLoc); /* Amount to space */
else
j = 1; /* Default to one line */
for (i = 0; i < j; i++) {
if (LnCnt >= LnMax)
break; /* Page overflow */
xputs (&List, "\n"); /* Space one line */
}
}
break;
case Title: /* TTL */
s = Line + SrcLoc;
t = TTLstring;
while (*s && (s < (TTLstring+MAXLINE)))
*t++ = *s++; /* Get title string */
*t = '\0';
if (LineCount > 1) {
LnCnt = LnMax; /* Skip to a new page */
} else {
if (Pass2) {
xputs (&List, TTLstring);
xputs (&List, "\n\n");
}
LnCnt += 2; /* Don't skip at start of file */
}
break;
case Cnop: /* CNOP */
i = TRUE; /* "Error-free" flag */
ObjSrc = GetValue (SrcOp, SrcLoc);
if (DefLine2 >= LineCount) {
Error (SrcLoc, FwdRef); /* Illegal forward reference */
i = FALSE;
}
if (Hunk2 != ABSHUNK) {
Error (SrcLoc, AbsReq); /* Must be absolute! */
i = FALSE;
}
ObjDest = GetValue (DestOp, DestLoc);
if (DefLine2 >= LineCount) {
Error (DestLoc, FwdRef); /* Illegal forward reference */
i = FALSE;
}
if (Hunk2 != ABSHUNK) {
Error (DestLoc, AbsReq); /* Must be absolute! */
i = FALSE;
}
templong = ObjDest;
while ((templong > 0) && ((templong & 1) == 0))
templong >>= 1; /* Shift out low-order zeros */
if ((templong != 1) || (ObjDest == 1)) {
Error (DestLoc, OperErr); /* DestOp must be a power of 2 */
i = FALSE;
}
if ((ObjSrc & 1) || (ObjSrc >= ObjDest)) {
Error (SrcLoc, OperErr); /* SrcOp is odd or out of range */
i = FALSE;
}
if (i) { /* If no errors so far */
AddrCnt = AddrBndW (AddrCnt);
templong = (AddrCnt & ~(ObjDest-1)) + ObjSrc;
if (templong < AddrCnt)
templong += ObjDest; /* We must advance to here */
if ((templong - AddrCnt) < MAXLINE) {
nX = templong - AddrCnt;
for (j = 0; j < nX; ) {
ObjString[j++] = NOP / 256;
ObjString[j++] = NOP & 255;
}
AddrAdv = InstSize = nX; /* generate NOPs */
PrntAddr = MakeHunk = TRUE;
} else {
Error (DestLoc, OperErr); /* Too many NOPs */
}
}
break;
case Include: /* INCLUDE */
if (Pass2 /* If we can skip */
&& (SkipIdx < SkipLim) /* this INCLUDE */
&& (LineCount == SkipIdx->Start)) { /* file in pass */
LineCount = SkipIdx->Finish; /* 2, do so. */
MacCount = SkipIdx->MCount;
if ((sf = SkipIdx->Set1) != NULL) {
while ((sf >= SetFixLim) && (sf->Sym != NULL)) {
(sf->Sym)->Val = sf->Val; /* Fix up SET symbols */
(sf->Sym)->Hunk = sf->Hunk;
sf--;
}
}
SkipIdx++;
break;
}
if ((Quiet < 0) && (InF->UPtr == 0))
ShowLine (InF->Line); /* Show where we are */
s = Line + SrcLoc;
if ((*s == '"') || (*s == '\''))
s++; /* Ignore quotes */
t = tempop;
while (!isspace(*s)
&& (*s != '"')
&& (*s != '\'')
&& (*s != '\0'))
*t++ = *s++;
*t = '\0';
if (InF->UPtr == 0) {
InF->Pos = lseek (In.fd, 0L, 1);
InF->Pos -= In.Lim-In.Ptr; /* Position in outer file */
}
if (!OpenIncl (tempop, InclList)) {
Error (SrcLoc, NoIncl); /* Couldn't open file */
InclErrs = TRUE;
if (InF->UPtr == 0) {
In.fd = open (InF->NPtr, 0);
lseek (In.fd, InF->Pos, 0);
In.Ptr = In.Lim = In.Buf;
}
break; /* Return to outer file */
}
InFNum++; /* Bump nesting level */
if (--InF < LowInF)
LowInF = InF;
Heap2Space (strlen(tempop)+1); /* Check for space */
InF->UPtr = 0; /* Not a user macro */
InF->NPtr = NextFNS; /* New stack pointer */
strcpy (NextFNS, tempop); /* File name */
NextFNS += strlen (tempop) + 1; /* Next available space */
if (NextFNS > High2)
High2 = NextFNS; /* Set high-water mark */
InF->NArg = -1; /* Indicate it's not a macro */
InF->Line = 0; /* Clear line counter */
InF->MCnt = MacCount;
if (!Pass2 && (SuppList || ListOff) && (IncStart == 0)) {
s = (char *) SkipLim + sizeof (struct SkipEnt);
if (s <= (char *) SetFixLim) {
SkipLim->Set1 = NULL; /* Save starting position */
IncStart = LineCount; /* in case we can skip */
IncPtr = InF; /* this file in pass 2. */
}
}
break;
case Set: /* SET */
if (Label[0] == '\0')
Error (0, NeedLab); /* Need a label */
ObjSrc = GetValue (SrcOp, SrcLoc);
if (DefLine2 >= LineCount)
Error (SrcLoc, FwdRef); /* Illegal forward reference */
Src.Hunk = Hunk2;
if (!ReadSymTab (Label)) /* Make a new entry */
AddSymTab (Label, ObjSrc, Src.Hunk, LineCount, 4);
else if (Sym->Flags & 4) { /* Re-SET the symbol */
Sym->Val = ObjSrc; /* SET value */
Sym->Hunk = Src.Hunk; /* Hunk number */
Sym->Defn = LineCount; /* Statement number */
}
PrntAddr = MakeHunk = TRUE;
if (!Pass2 && (IncStart != 0)) {
if ((sf = SkipLim->Set1) != NULL) {
while (sf >= SetFixLim) {
if (sf->Sym != Sym) {
sf--;
} else {
sf->Val = Sym->Val; /* Update an */
sf->Hunk = Sym->Hunk; /* existing entry. */
return (Set);
}
}
}
sf = SetFixLim;
sf--;
s = (char *) SkipLim + sizeof (struct SkipEnt);
if (s > (char *) sf) {
IncStart = 0; /* No room for set symbol */
if (SkipLim->Set1 != NULL) {
SetFixLim = SkipLim->Set1;
SetFixLim++;
}
} else {
if (SkipLim->Set1 == NULL)
SkipLim->Set1 = sf; /* First SET symbol in INCLUDE */
sf->Sym = Sym;
sf->Val = Sym->Val; /* Save SET symbol value */
sf->Hunk = Sym->Hunk; /* and hunk. */
SetFixLim = sf;
}
}
break;
case Macro: /* MACRO */
if (Label[0] == '\0')
Error (0, NeedLab); /* Need a label */
s = Label;
t = tempop;
*t++ = ' '; /* Prepend name with a */
while (*s) /* blank and convert */
*t++ = toupper (*s++); /* it to upper case. */
*t = '\0';
if (!Pass2) { /* Pass 1 */
if (!ReadSymTab (tempop)) /* Save MACRO name */
AddSymTab (tempop, 0L, 0L, LineCount, 8);
Sym->Hunk = (long) AddName(Line,1); /* Save MACRO stmt. */
} else { /* Pass 2 */
ReadSymTab (tempop);
if (Sym->Defn != LineCount) {
Error (LabLoc, DupMac); /* Duplicate MACRO */
AddRef (LineCount);
}
WriteListLine (&List); /* Echo MACRO */
}
i = 0; /* IF nest counter */
while (1) { /* Process macro body */
if (LineParts (dummy)) {
Error (OpLoc, NoENDM); /* Premature EOF */
i = 0;
break;
}
if ((i += CountNest (OpCode)) < 0) {
Error (OpLoc,ManyENDC); /* Unmatched ENDC */
i = 0;
}
if (!Pass2)
AddName (Line, 2); /* Store a line */
if (strcmp (OpCode, "ENDM") == 0)
break; /* Main program echoes ENDM */
if (Pass2)
WriteListLine (&List); /* Echo a line */
}
if (i > 0)
Error (OpLoc, NoENDC); /* ENDC is missing */
break;
case IfEQ: /* IFEQ */
ObjSrc = GetValue (SrcOp, SrcLoc);
if (ObjSrc != 0)
SkipNest++; /* Skip to the next ENDC */
break;
case IfNE: /* IFNE */
ObjSrc = GetValue (SrcOp, SrcLoc);
if (ObjSrc == 0)
SkipNest++;
break;
case IfGT: /* IFGT */
ObjSrc = GetValue (SrcOp, SrcLoc);
if (ObjSrc <= 0)
SkipNest++;
break;
case IfGE: /* IFGE */
ObjSrc = GetValue (SrcOp, SrcLoc);
if (ObjSrc < 0)
SkipNest++;
break;
case IfLT: /* IFLT */
ObjSrc = GetValue (SrcOp, SrcLoc);
if (ObjSrc >= 0)
SkipNest++;
break;
case IfLE: /* IFLE */
ObjSrc = GetValue (SrcOp, SrcLoc);
if (ObjSrc > 0)
SkipNest++;
break;
case IfC: /* IFC */
if (strcmp (SrcOp, DestOp) != 0)
SkipNest++;
break;
case IfNC: /* IFNC */
if (strcmp (SrcOp, DestOp) == 0)
SkipNest++;
break;
case IfD: /* IFD */
if (ReadSymTab (SrcOp))
AddRef (LineCount);
if (DefLine2 > LineCount)
SkipNest++;
break;
case IfND: /* IFND */
if (ReadSymTab (SrcOp))
AddRef (LineCount);
if (DefLine2 <= LineCount)
SkipNest++;
break;
case EndC: /* ENDC */
break; /* LineParts will take care of it */
case Section: /* SECTION */
if (SFormat)
Error (OpLoc, NotSFmt); /* Not in S-format */
tempop[0] = '\0';
s = Line + DestLoc + strlen (DestOp); /* Check for flags */
if (*s == ',') {
s++;
GetField (s, tempop); /* Get specification */
}
DoSection (SrcOp, SrcLoc, DestOp, DestLoc, tempop, j);
break;
case CSeg: /* CODE */
if (SFormat)
Error (OpLoc, NotSFmt); /* Not in S-format */
DoSection (SrcOp, SrcLoc, "CODE", OpLoc, DestOp, DestLoc);
break; /* Treat as SECTION */
case DSeg: /* DATA */
if (SFormat)
Error (OpLoc, NotSFmt); /* Not in S-format */
DoSection (SrcOp, SrcLoc, "DATA", OpLoc, DestOp, DestLoc);
break; /* Treat as SECTION */
case BSS: /* BSS */
if (SFormat)
Error (OpLoc, NotSFmt); /* Not in S-format */
DoSection (SrcOp, SrcLoc, "BSS", OpLoc, DestOp, DestLoc);
break; /* Treat as SECTION */
case Idnt: /* IDNT */
s = Line + SrcLoc;
if ((*s == '"') || (*s == '\''))
s++; /* Ignore quotes */
t = IdntName;
while (!isspace(*s)
&& (*s != '"')
&& (*s != '\'')
&& (*s != '\0'))
*t++ = *s++;
*t = '\0';
break;
case DCB: /* DCB */
if ((Size == Word) || (Size == Long))
AddrCnt = AddrBndW (AddrCnt);
ObjSrc = GetValue (SrcOp, SrcLoc); /* Replication factor */
if (DefLine2 >= LineCount) {
Error (SrcLoc, FwdRef); /* Illegal forward reference */
ObjSrc = 0;
}
if (Hunk2 != ABSHUNK) {
Error (SrcLoc, AbsReq); /* Must be absolute! */
ObjSrc = 0;
}
ObjDest = GetValue (DestOp, DestLoc); /* Value to replicate */
Dest.Hunk = Hunk2;
for (i = 0; i < ObjSrc; i++) {
if (nX >= MAXLINE) {
Error (SrcLoc, DCOflo); /* ObjString overflowed */
break;
}
if (Dest.Hunk != ABSHUNK) {
templong = AddrCnt + nX; /* Relocatable */
PutRel (templong, Hunk2, Size);
}
if (Size == 4) {
ObjString[nX++] = (ObjDest >> 24) & 0x00FF;
ObjString[nX++] = (ObjDest >> 16) & 0x00FF;
}
if (Size >= 2)
ObjString[nX++] = (ObjDest >> 8) & 0x00FF;
ObjString[nX++] = ObjDest & 0x00FF;
}
AddrAdv = InstSize = nX;
PrntAddr = MakeHunk = TRUE;
break;
case Equr: /* EQUR */
if ((i = IsRegister (SrcOp, strlen (SrcOp))) < 0)
Error (SrcLoc, AddrErr); /* Not a valid register */
if (Label[0] == '\0')
Error (0, NeedLab); /* Need a label */
else {
if (!ReadSymTab (Label)) /* Make a new entry */
AddSymTab (Label, (long) i, 0L, LineCount, 0x20);
GotEqur = TRUE; /* We have at least one EQUR */
}
break;
case Reg: /* REG */
if (Label[0] == '\0')
Error (0, NeedLab); /* Need a label */
else {
if ((i = GetMultReg (SrcOp, SrcLoc)) == 0) {
Error (SrcLoc, OperErr);
} else {
if (!ReadSymTab (Label)) { /* Make a new entry */
AddSymTab (Label, (long) i, 0L, LineCount, 0x40);
GotEqur = TRUE; /* We have at least one EQUR */
}
}
}
break;
case Near: /* NEAR */
SmallData = TRUE; /* Set small-data model flag */
AnyNear = TRUE; /* Remember that we use it somewhere */
break;
case Far: /* FAR */
SmallData = FALSE; /* Reset small-data model flag */
break;
default:
break;
}
return (Dir);
}
DoSection (name, nameloc, type, typeloc, flags, flagloc)
char *name, *type, *flags;
int nameloc, typeloc, flagloc;
/* Processes SECTION directive or equivalent */
{
static long HunkPos; /* Seek address of start of section */
register char *s, *t;
long newflags, templong;
char tempop[MAXLINE];
PrntAddr = TRUE;
for (s = type; *s; s++) /* Convert section type */
*s = toupper (*s); /* to upper case */
if ((type[0] == '\0') || (strcmp (type, "CODE") == 0))
newflags = HunkCode; /* Code section */
else if (strcmp (type, "DATA") == 0)
newflags = HunkData; /* Data section */
else if (strcmp (type, "BSS") == 0)
newflags = HunkBSS; /* BSS section */
else {
Error (typeloc, OperErr); /* Invalid type */
strcpy (type, "CODE");
newflags = HunkCode; /* Make it CODE */
}
newflags <<= 16; /* Shift to high-order 16 bits */
if (flags[0]) {
for (s = flags; *s; s++) /* Convert flags */
*s = toupper (*s); /* to upper case */
if (strcmp (flags, "CHIP") == 0)
newflags |= MEMF_CHIP; /* CHIP memory */
else if (strcmp (flags, "FAST") == 0)
newflags |= MEMF_FAST; /* FAST memory */
else
Error (flagloc, OperErr); /* Invalid - ignore */
}
templong = (newflags & 0xFFFF0000) >> 16;
sprintf (tempop," %4x",HunkSeq++); /* Make section name unique */
s = name;
if ((*s == '"') || (*s == '\''))
s++; /* Ignore quotes */
t = tempop + 6;
while (!isspace(*s)
&& (*s != '"')
&& (*s != '\'')
&& (*s != '\0'))
*t++ = *s++; /* Concatenate section name */
*t = '\0';
if (ReadSymTab (tempop)) { /* Scan for section name */
if (HunkType == HunkNone) {
SectLine = 1; /* Start of first section */
} else {
if (Pass2) {
AddRef (LineCount);
DumpSdata (&Srec); /* Finish the previous hunk */
if (!MakeHunk) { /* If it was a null hunk, */
if (Srec.Ptr > Srec.Buf) /* overwrite it. */
write (Srec.fd, Srec.Buf, Srec.Ptr - Srec.Buf);
lseek (Srec.fd, HunkPos, 0);
Srec.Ptr = Srec.Buf;
}
} else {
AddrCnt = AddrBndL (AddrCnt); /* Finish on long word */
}
if (AddrCnt > OrgHigh)
Sect->Val = AddrCnt; /* End of old section */
else
Sect->Val = OrgHigh; /* We've ORGed higher */
SectLine = LineCount; /* Start of new section */
}
Sect = Sym; /* Point to new section */
AddrCnt = SectStart = Sym->Val; /* Continuation */
OrgHigh = 0L;
OrgFlag = FALSE;
TempAddr = StartAddr = AddrCnt;
CurrHunk = Sym->Hunk & 0x0000FFFFL; /* Hunk no. */
HunkType = (Sym->Hunk & 0x3FFF0000L) >> 16; /* Type */
HunkFlags = Sym->Hunk & 0xC0000000L; /* Flags */
if (Pass2 && !SFormat) { /* Start a new hunk */
HunkPos = lseek (Srec.fd, 0L, 1);
HunkPos += Srec.Ptr - Srec.Buf; /* It starts here */
templong = HunkName;
xputl (&Srec, templong);
if (tempop[6])
DumpName (&Srec, &tempop[6], 0L); /* Hunk name */
else
DumpName (&Srec, " ", 0L);
xputl (&Srec, HunkType); /* Hunk type */
LenPtr = Srec.Ptr; /* Pointer to hunk length */
LenPos = lseek (Srec.fd, 0L, 1);
LenPos += LenPtr-Srec.Buf; /* Hunk length goes here */
xputl (&Srec, 0L); /* For now, set it to zero */
}
MakeHunk = FALSE; /* We don't have anything yet */
if (AnyNear && (CurrHunk > 1))
Error (OpLoc, ManySect); /* Too many hunks for small data */
return;
}
AddrCnt = AddrBndL (AddrCnt); /* Finish on long word bounary */
if (Pass2) {
Error (OpLoc, ManySect); /* Table overflowed in pass 1 */
return;
}
if (NextHunk >= ABSHUNK) /* Set up a new table entry */
return; /* Section table overflow */
if (HunkType != HunkNone) {
if (AddrCnt > OrgHigh)
Sect->Val = AddrCnt; /* End of old section */
else
Sect->Val = OrgHigh; /* We've ORGed higher */
SectLine = LineCount; /* Starting line number */
} else {
SectLine = 1; /* Start of first section */
}
AddrCnt = SectStart = OrgHigh = 0L; /* Reset location counter */
OrgFlag = FALSE;
TempAddr = StartAddr = AddrCnt;
HunkType = (newflags & 0x3FFF0000L) >> 16; /* Type */
HunkFlags = newflags & 0xC0000000L; /* Flags */
CurrHunk = NextHunk++; /* Bump next hunk number */
newflags |= CurrHunk; /* Add hunk number */
AddSymTab (tempop, 0L, newflags, LineCount, 16); /* New entry */
Sect = Sym; /* Pointer to new entry */
MakeHunk = FALSE; /* We don't have anything yet */
if (AnyNear && (CurrHunk > 1))
Error (OpLoc, ManySect); /* Too many hunks for small data */
return;
}
SHAR_EOF
cat << \SHAR_EOF > Codegen.c
/*------------------------------------------------------------------*/
/* */
/* MC68000 Cross Assembler */
/* */
/* Copyright (c) 1985 by Brian R. Anderson */
/* */
/* Object code generator - January 6, 1989 */
/* */
/* This program may be copied for personal, non-commercial use */
/* only, provided that the above copyright notice is included */
/* on all copies of the source code. Copying for any other use */
/* without the consent of the author is prohibited. */
/* */
/*------------------------------------------------------------------*/
/* */
/* Originally published (in Modula-2) in */
/* Dr. Dobb's Journal, April, May, and June 1986. */
/* */
/* AmigaDOS conversion copyright 1989 by Charlie Gibbs. */
/* */
/*------------------------------------------------------------------*/
#include <stdio.h>
#include "a68kdef.h"
#include "a68kglb.h"
/* Functions */
extern int LineParts(), Instructions(), ObjDir();
extern int GetInstModeSize(), GetMultReg(), CountNest();
extern int ReadSymTab(), GetArgs(), GetAReg(), OpenIncl();
extern long AddrBndW(), AddrBndL(), GetValue(), CalcValue();
extern char *AddName(), *GetField();
extern struct SymTab *NextSym();
extern struct SymTab **HashIt();
GetObjectCode (dummy) int dummy;
/* Determines the object code for the operation as well as the operands */
/* Returns each (up to 3 fields), along with the length of each. */
{
int quick;
int ExtL; /* Bit pattern for instruction extension word */
long templong;
char tempop[MAXLINE];
register int i, j;
i = Instructions (OpLoc); /* Analyze the opcode */
if (Dir != None) {
ObjDir (dummy); /* Process directives */
return;
}
if ((Label[0] != '\0') || (OpCode[0] != '\0'))
PrntAddr = TRUE; /* Print address at least */
if (OpCode[0] == '\0') {
MakeHunk |= PrntAddr;
return; /* No op code, exit now */
}
if (!i) { /* Unrecognized opcode */
if ((Quiet < 0) && (InF->UPtr == 0))
ShowLine (InF->Line); /* Show where we are */
if (OpCode[0] == '*') {
Error (OpLoc, NoCode); /* Don't try to open the console! */
return;
}
if (Size == Byte) /* Set up \0 parameter */
MacSize[0] = 'B';
else if (Size == Long)
MacSize[0] = 'L';
else
MacSize[0] = 'W';
AddrAdv = InstSize = 0;
PrntAddr = FALSE;
Dir = MacCall; /* Assume it's a macro call */
if (InF->UPtr == 0) { /* If we're reading from a file */
InF->Pos = lseek (In.fd, 0L,1); /* remember where we are. */
InF->Pos -= In.Lim - In.Ptr;
}
tempop[0] = ' ';
tempop[1] = '\0';
strcat (tempop, OpCode); /* Prepend a blank to OpCode */
if (ReadSymTab (tempop)) { /* Search for user macro */
AddRef (LineCount);
if(Sym->Defn < LineCount) { /* Only if previously defined! */
InFNum++;
if (--InF < LowInF)
LowInF = InF;
MacCount++;
Heap2Space (0); /* Check for space */
InF->UPtr = (char *) Hunk2; /* MACRO statement */
InF->UPtr += strlen(InF->UPtr) + 1; /* Skip over it */
InF->NPtr = NextFNS; /* New stack pointer */
InF->Line = 0; /* Line number in macro */
InF->NArg=GetArgs (""); /* Get arguments */
InF->MCnt = MacCount; /* Macro number */
if (OuterMac == 0)
OuterMac = InFNum; /* Outer macro */
return;
}
}
if (!OpenIncl (OpCode, InclList)) {
Error (OpLoc, NoCode); /* Couldn't open file */
Dir = BadMac; /* Invalid macro */
if (InF->UPtr == 0) {
In.fd = open (InF->NPtr, 0);
lseek (In.fd, InF->Pos, 0);
In.Ptr = In.Lim = In.Buf;
}
return; /* Return to outer file */
}
InFNum++; /* Bump nesting level */
if (--InF < LowInF)
LowInF = InF;
MacCount++;
Heap2Space (0); /* Check for space */
InF->UPtr = 0; /* Not a user macro */
InF->NPtr = NextFNS; /* New stack pointer */
InF->Line = 0; /* Line number in macro */
InF->NArg = GetArgs (OpCode); /* Get arguments */
InF->MCnt = MacCount; /* Macro number */
if (OuterMac == 0)
OuterMac = InFNum; /* Outer macro */
return;
}
MakeHunk = TRUE; /* We have something for a hunk */
AddrCnt = AddrBndW (AddrCnt); /* It'll be word-aligned */
if ((AdrModeA != 0) || (AdrModeB != 0)) {
Src.Loc = SrcLoc;
Dest.Loc = DestLoc;
GetOperand (SrcOp, &Src, SrcPC IN AdrModeB ? 2 : 0);
GetOperand (DestOp, &Dest, EA05c IN AdrModeB ? 4 : 0);
}
if (EA05z IN AdrModeB) { /* MOVEM */
if ((Src.Mode != MultiM) && (Dest.Mode != MultiM)) {
OpCode[4] = '\0'; /* MOVEM of a single register */
Instructions (OpLoc); /* becomes a straight MOVE */
}
}
if ((Src.Mode == Imm) /* Immediate instructions */
&& (Src.Hunk == ABSHUNK) && (Src.Defn < LineCount)
&& (((EA611 IN AdrModeB) && (Dest.Mode == DReg) /* MOVE */
&& (Size == Long) && (Src.Value >= -128) && (Src.Value <= 127))
|| ((EA05y IN AdrModeB) /* ADD/SUB */
&& (Src.Value > 0) && (Src.Value <= 8)))) {
strcat (OpCode, "Q"); /* Make it ADDQ/SUBQ/MOVEQ */
Instructions (OpLoc);
}
else if ((Dest.Mode == ARDir) && (Src.Mode <= 12)
&& (((EA05y | EA611) IN AdrModeB) /* ADD, SUB, or MOVE */
|| (OpM68C IN AdrModeA))) { /* CMP */
strcat (OpCode, "A"); /* ADD op,An becomes ADDA etc. */
Instructions (OpLoc);
}
else if ((Src.Mode == Imm) /* Immediate instructions */
&& ((OpM68D | OpM68C | OpM68X) IN AdrModeA)) {
strcat (OpCode, "I"); /* ADD/AND/OR/SUB, CMP, EOR */
Instructions (OpLoc); /* ADD #op,d becomes ADDI etc. */
}
else if ((Src.Mode == ARPost) && (Dest.Mode == ARPost)
&& (OpM68C IN AdrModeA)) { /* CMP */
strcat (OpCode, "M"); /* Generate CMPM if necessary */
Instructions (OpLoc);
}
/*=================== Operand validation routines ====================*/
if (Pass2) {
/* If an immediate operand isn't absolute, it must be a long word */
if ((Src.Mode == Imm) && (Size != Long) && (Src.Hunk != ABSHUNK))
Error (SrcLoc, RelErr);
/* ------- Check for instructions with too many operands. ------- */
/* Some specialized instruction routines contain their own tests. */
if (AdrModeA == 0) { /* Should have only one operand */
if ((AdrModeB == EA05e) || (AdrModeB == (Size67 | EA05e))) {
if (Dest.Mode != Null)
Error (DestLoc, OperErr);
/* } else if (AdrModeB == 0) { */ /* Should have no operands */
/* if (Src.Mode != Null)
Error (SrcLoc, OperErr);
if (Dest.Mode != Null)
Error (DestLoc, OperErr); De-activated for now */
}
}
if ((AdrModeA != 0) || (AdrModeB != 0)) {
if(Dest.Mode != NULL) { /* We should never find 3 operands */
j = DestLoc + strlen (DestOp);
if ((Line[j] != '\0')
&& (Line[j] != ';')
&& (!isspace (Line[j]))) {
Error (j, OperErr);
}
}
/* ---------------- Check for missing operands. ----------------- */
if (Src.Mode == Null) {
Error (OpLoc+strlen(OpCode), OperErr); /* No source */
} else if (Dest.Mode == Null) {
if (((ImmMode & AdrModeB) == ImmMode)
|| (TwoOpsA IN AdrModeA)
|| (TwoOpsB IN AdrModeB)) {
Error (SrcLoc+strlen(SrcOp), OperErr); /* No dest. */
}
}
}
}
/*====================================================================*/
/* ---------------- Decrement and Branch (DBcc) ----------------- */
if (DecBr IN AdrModeA) {
if (Pass2) {
if (Src.Mode != DReg)
Error (SrcLoc, ModeErr);
if (Dest.Value & 1)
Error (DestLoc, AlignErr); /* Boundary alignment error */
if (Dest.Hunk == CurrHunk) {
ObjSrc = Dest.Value-AddrCnt-2; /* Relative branch distance */
Dest.Hunk = ABSHUNK; /* Displacement is absolute */
} else
ObjSrc = 0; /* Let the linker worry about it */
if ((ObjSrc > 32767) || (ObjSrc < -32768))
Error (DestLoc,BraErr); /* Too far to branch */
if (Dest.Hunk!=CurrHunk) { /* DBcc to another section */
templong = AddrCnt + 2; /* 16-bit relocatable */
PutRel (templong, Dest.Hunk, 2);
}
ObjOp = Op | Src.Rn;
}
AddrAdv = 4;
nO = nS = 2;
return;
}
/* ------------ Branch (Bcc, including BRA and BSR) ------------- */
if (Brnch IN AdrModeA) {
if (Src.Value & 1)
Error (SrcLoc, AlignErr); /* Boundary alignment error */
if (Src.Hunk == CurrHunk) {
ObjSrc=Src.Value-AddrCnt-2; /* Relative branch distance */
Src.Hunk = ABSHUNK; /* Displacement is absolute */
if (Size != Byte) {
if ((ObjSrc >= -128) && (ObjSrc <= 127) && (ObjSrc != 0))
if (DefLine2 < LineCount)
Size = Byte; /* Short branch if possible */
else if (Pass2 && FwdProc && (Size != Byte))
FwdShort=TRUE; /* Fwd. ref. could be made short */
}
if ((Size == Byte) && (ObjSrc == 0))
Error (SrcLoc, BccSDsp0); /* Can't do this! */
} else {
ObjSrc = 0; /* Let the linker worry about it */
if (Size == Byte)
Error (SrcLoc, BraErr); /* No external short branches! */
}
if (Size != Byte) {
InstSize = 4;
nS = 2;
templong = 32767;
} else {
InstSize = 2;
Op |= (ObjSrc & 0x00FF);
templong = 127;
}
if ((ObjSrc > templong) || (ObjSrc < -templong-1))
Error (SrcLoc, BraErr); /* Too far to branch */
if (Dest.Mode != Null)
Error (DestLoc, OperErr); /* No Destination operand! */
AddrAdv = InstSize;
ObjOp = Op;
nO = 2;
if (Src.Hunk != CurrHunk) { /* Bcc to another section */
templong = AddrCnt + 2; /* 16-bit relocatable */
PutRel (templong, Src.Hunk, 2);
}
return;
}
/* ------------ Check for short (16-bit) JMP or JSR ------------- */
if ((Op == JMP) || (Op == JSR))
if ((Size == Byte) && (Src.Mode == AbsL))
Src.Mode = AbsW;
/* Uses information from Instructions & GetOperand (among others) */
/* to complete calculation of Object Code. */
/* Op, AdrModeA, AdrModeB, Size, and Src & Dest records are all */
/* Global variables imported from the SyntaxAnalyzer MODULE. */
ExtL = 0;
quick = FALSE;
/* ------------ Check for boundary alignment errors. ------------ */
/* BCHG, BCLR, BSET, BTST, LEA, NBCD, PEA, Scc, TAS are exempt. */
if (Pass2) {
if ((Size != Byte)
&& (Op != LEA)
&& (Op != PEA)
&& !((AdrModeA == 0) && (AdrModeB == 0))
&& !(AdrModeB & EA05c) /* BTST */
&& !((AdrModeB&EA05e) && (AdrModeA==0) && !(AdrModeB&Size67))) {
if (Src.Value & 1)
if ((Src.Mode >= ARDisp) && (Src.Mode <= PCDisX))
Error (SrcLoc, AlignErr);
if (Dest.Value & 1)
if ((Dest.Mode >= ARDisp) && (Dest.Mode <= PCDisX))
Error (DestLoc, AlignErr);
}
/* Check for 5 special cases first */
if (Op == STOP) {
if (Src.Mode != Imm)
Error (SrcLoc, OperErr);
if (Dest.Mode != Null)
Error (DestLoc, OperErr);
}
if (Op == LINK) {
Op |= Src.Rn;
if (Src.Mode != ARDir)
Error (SrcLoc, ModeErr);
if (Dest.Mode != Imm)
Error (DestLoc, ModeErr);
else if (Dest.Value & 1)
Error (DestLoc, AlignErr); /* Boundary alignment error */
}
if (Op == SWAP) {
if (!(EA05f IN AdrModeB)) { /* Ignore if PEA instruction */
Op |= Src.Rn;
if (Src.Mode != DReg)
Error (SrcLoc, OperErr);
if (Dest.Mode != Null)
Error (DestLoc, OperErr);
}
}
if (Op == UNLK) {
Op |= Src.Rn;
if (Src.Mode != ARDir)
Error (SrcLoc, OperErr);
if (Dest.Mode != Null)
Error (DestLoc, OperErr);
}
/* Now do generalized address modes */
if ((Ry02 IN AdrModeA)&&(Rx911 IN AdrModeA)) { /* 2 registers */
if (Op == CMPM) { /* Special routine for CMPM */
Op |= Src.Rn | (Dest.Rn << 9);
if (Src.Mode != ARPost)
Error (SrcLoc, ModeErr);
if (Dest.Mode != ARPost)
Error (DestLoc, ModeErr);
} else { /* Other two-register instructions */
Op |= Src.Rn | (Dest.Rn << 9);
if (RegMem3 IN AdrModeA) {
if (Src.Mode == DReg) {
if (Dest.Mode != DReg)
Error (DestLoc, ModeErr);
} else if (Src.Mode == ARPre) {
Op |= 0x0008;
if (Dest.Mode != ARPre)
Error (DestLoc, ModeErr);
} else
Error (SrcLoc, OperErr);
} else {
if (Src.Mode == ARPost)
if (Dest.Mode != ARPost)
Error (DestLoc, ModeErr);
else
Error (SrcLoc, OperErr);
}
}
}
}
if (Data911 IN AdrModeA) { /* Data in 9-11 (ADDQ/SUBQ) */
quick = TRUE;
if (Src.Mode == Imm)
if ((Src.Value > 0) && (Src.Value <= 8)) {
if (Src.Value < 8) /* Data of 8 is coded as 000 */
Op |= Src.Value << 9;
} else
Error (SrcLoc, SizeErr);
else
Error (SrcLoc, OperErr);
}
if (CntR911 IN AdrModeA) { /* Only Shift/Rotate use this */
if (Dest.Mode == DReg) {
Op = (Op & 0xF9FF) | Dest.Rn;
if (Size == Word) Op |= 0x0040;
if (Size == Long) Op |= 0x0080;
if (Src.Mode == DReg)
Op |= 0x0020 | (Src.Rn << 9);
else if (Src.Mode == Imm) {
quick = TRUE;
/* Range Check */
if ((Src.Value > 0) && (Src.Value <= 8)) {
if (Src.Value < 8) /* Data of 8 is coded as 000 */
Op |= (Src.Value << 9);
} else
Error (SrcLoc, SizeErr);
} else
Error (SrcLoc, OperErr);
} else if (Dest.Mode == Null) {
Op = (Op & 0xFFE7) | 0x00C0;
EffAdr (&Src, (mea | aea));
} else
Error (SrcLoc, OperErr);
}
if (Data03 IN AdrModeA) { /* TRAP Vector in 0-3 */
quick = TRUE;
if (Src.Mode == Imm)
if ((Src.Value >= 0) && (Src.Value < 16))
Op |= Src.Value;
else
Error (SrcLoc, SizeErr);
else
Error (SrcLoc, OperErr);
if (Dest.Mode != Null)
Error (DestLoc, OperErr);
}
if (Data07 IN AdrModeA) { /* Data in 0-7 (MOVEQ) */
quick = TRUE;
Op |= (Src.Value & 0x00FFL) | (Dest.Rn << 9);
if (Src.Mode != Imm)
Error (SrcLoc, ModeErr);
else if (Dest.Mode != DReg)
Error (DestLoc, ModeErr);
else if ((Src.Value < -128) || (Src.Value > 127))
Error (SrcLoc, SizeErr);
}
if (Pass2) {
if (OpM68D IN AdrModeA) { /* DReg in 6-8 (ADD/AND/OR/SUB) */
if (Dest.Mode == DReg) {
Op |= (Dest.Rn << 9);
if ((Src.Mode == ARDir) && (Size == Byte))
Error (SrcLoc, SizeErr);
} else /* Assume Src.Mode = DReg -- Error trapped elsewhere */
Op |= (Src.Rn << 9) | 0x0100;
if (Size == Word) Op |= 0x0040;
if (Size == Long) Op |= 0x0080;
}
if (OpM68A IN AdrModeA) { /* AReg in 6-8 (ADDA/CMPA/SUBA) */
if (Dest.Mode == ARDir)
Op |= (Dest.Rn << 9);
else
Error (DestLoc, ModeErr);
if (Size == Byte) Error (OpLoc+5, SizeErr);
if (Size == Word) Op |= 0x00C0;
if (Size == Long) Op |= 0x01C0;
}
if (OpM68C IN AdrModeA) { /* CMP (Compare) */
if (Dest.Mode == DReg)
Op |= (Dest.Rn << 9);
else
Error (DestLoc, ModeErr);
if (Size == Byte) {
if (Src.Mode == ARDir)
Error (OpLoc+4, SizeErr);
}
if (Size == Word) Op |= 0x0040;
if (Size == Long) Op |= 0x0080;
}
if (OpM68X IN AdrModeA) { /* EOR (Exclusive or) */
if (Src.Mode == DReg)
Op |= (Src.Rn << 9);
else
Error (SrcLoc, ModeErr);
if (Size == Byte) Op |= 0x0100;
if (Size == Word) Op |= 0x0140;
if (Size == Long) Op |= 0x0180;
}
if (OpM68S IN AdrModeA) { /* EXT (Sign extension) */
if (Src.Mode == DReg)
Op |= Src.Rn;
else
Error (SrcLoc, ModeErr);
if (Dest.Mode != Null)
Error (DestLoc, OperErr);
if (Size == Byte) Error (OpLoc+4, SizeErr);
if (Size == Word) Op |= 0x0080;
if (Size == Long) Op |= 0x00C0;
}
if (OpM68R IN AdrModeA) { /* MOVEP (Register/memory) */
if ((Src.Mode == DReg) && (Dest.Mode == ARDisp)) {
if (Size == Byte) Error (OpLoc+6, SizeErr);
if (Size == Word) Op |= 0x0180;
if (Size == Long) Op |= 0x01C0;
Op |= (Src.Rn << 9) | Dest.Rn;
} else if ((Src.Mode == ARDisp) && (Dest.Mode == DReg)) {
if (Size == Byte) Error (OpLoc+6, SizeErr);
if (Size == Word) Op |= 0x0100;
if (Size == Long) Op |= 0x0140;
Op |= Src.Rn | (Dest.Rn << 9);
} else
Error (SrcLoc, ModeErr);
}
if (OpM37 IN AdrModeA) { /* EXG (Exchange registers) */
if ((Src.Mode == DReg) && (Dest.Mode == DReg))
Op |= 0x0040 | (Src.Rn << 9) | Dest.Rn;
else if ((Src.Mode == ARDir) && (Dest.Mode == ARDir))
Op |= 0x0048 | (Src.Rn << 9) | Dest.Rn;
else if ((Src.Mode == ARDir) && (Dest.Mode == DReg))
Op |= 0x0088 | (Dest.Rn << 9) | Src.Rn;
else if ((Src.Mode == DReg) && (Dest.Mode == ARDir))
Op |= 0x0088 | (Src.Rn << 9) | Dest.Rn;
else
Error (SrcLoc, ModeErr);
}
if (Bit811 IN AdrModeB) { /* Bit operations using bits 8-11 */
Size = Word; /* Ignore size specification */
if (Src.Mode == DReg)
Op |= 0x0100 | (Src.Rn << 9);
else if (Src.Mode == Imm)
Op |= 0x0800;
else
Error (SrcLoc, ModeErr);
}
if (Size67 IN AdrModeB) { /* Size in bits 6-7 */
/* if (Size == Byte) ; No action -- bits are already 0 */
if (Size == Word) Op |= 0x0040;
if (Size == Long) Op |= 0x0080;
}
if (Size6 IN AdrModeB) { /* Size in bit 6 (MOVEM) */
if (Size == Byte) Error (OpLoc+6, SizeErr);
/* if (Size == Word) ; No Action -- bit is already 0 */
if (Size == Long) Op |= 0x0040;
}
if (Sz1213A IN AdrModeB) { /* Size in 12-13 (MOVE) */
if (Size == Byte) Op |= 0x1000;
if (Size == Word) Op |= 0x3000;
if (Size == Long) Op |= 0x2000;
}
if (Sz1213 IN AdrModeB) { /* Size in 12-13 (MOVEA) */
if (Dest.Mode == DReg) /* Can't be to data register! */
Error(DestLoc,ModeErr); /* (Others are caught elsewhere) */
Op |= (Dest.Rn << 9);
if (Size == Byte) Error (OpLoc+6, SizeErr);
if (Size == Word) Op |= 0x3000;
if (Size == Long) Op |= 0x2000;
}
if (EA05a IN AdrModeB) /* Effective address - all */
if ((Dest.Mode == DReg) || (Dest.Mode == ARDir))
EffAdr (&Src, ea);
else
Error (DestLoc, ModeErr);
if (EA05b IN AdrModeB) /* Eff. Addr. - all except ARDir */
if (Dest.Mode == DReg) {
EffAdr (&Src, dea);
Op |= (Dest.Rn << 9);
} else
Error (DestLoc, ModeErr);
if (EA05c IN AdrModeB) /* BTST */
EffAdr (&Dest, 0x0802); /* All but ARDir/Imm */
if(EA05d IN AdrModeB) { /* All but PC relative & immediate */
EffAdr (&Dest, aea);
if ((Dest.Mode == ARDir) && (Size == Byte))
Error (OpLoc+5, SizeErr);
}
if(EA05e IN AdrModeB) { /* All but ARDir, PC relative, Imm */
if (Dest.Mode == Null)
EffAdr (&Src, (dea | aea));
else if ((Src.Mode == Imm) || (Src.Mode == DReg))
EffAdr (&Dest, (dea | aea));
else
Error (SrcLoc, ModeErr);
}
if (EA05f IN AdrModeB) { /* JMP, JSR, LEA, and PEA */
EffAdr (&Src, cea);
if (Rx911 IN AdrModeA)
if (Dest.Mode == ARDir)
Op |= (Dest.Rn << 9); /* Address Reg. for LEA */
else
Error(DestLoc,ModeErr); /* Must load Address Reg. */
else
if (Dest.Mode != Null)
Error (DestLoc, OperErr); /* No Dest. unless LEA */
}
if (EA05x IN AdrModeB) { /* AND and OR */
if (Dest.Mode == DReg)
EffAdr (&Src, dea);
else if (Src.Mode == DReg)
EffAdr (&Dest, mea | aea);
else
Error (SrcLoc, OperErr);
}
if (EA05y IN AdrModeB) { /* ADD and SUB */
if (Dest.Mode == DReg) {
EffAdr (&Src, ea);
if ((Src.Mode == ARDir) && (Size == Byte))
Error (OpLoc+4, SizeErr);
} else if (Src.Mode == DReg)
EffAdr (&Dest, (mea | aea));
else
Error (SrcLoc, ModeErr);
}
}
if (EA05z IN AdrModeB) { /* MOVEM */
if (Pass2) {
if (Src.Mode == MultiM) { /* Move to memory */
EffAdr (&Dest, (mea | aea | 0x0008));
ExtL = Src.Value;
i = (Dest.Mode == ARPre); /* ExtL flip indicator */
} else if (Dest.Mode == MultiM) { /* Move from memory */
Op |= 0x0400; /* Set direction */
EffAdr (&Src, (mea | 0x0810));
ExtL = Dest.Value;
i = (Src.Mode == ARPre);
} else {
Error (SrcLoc, OperErr);
i = FALSE;
}
if (i) { /* Flip ExtL if ARPre */
j = 0;
for (i = 0; i < 8; i++)
j |= (ExtL & (1<<i)) << (15-i*2);
for (i = 8; i < 16; i++)
j |= (ExtL & (1<<i)) >> (i*2-15);
ExtL = j;
}
}
nO += 2; /* Extension is part of OpCode */
InstSize += 2;
}
if (Pass2) {
if (EA611 IN AdrModeB) { /* Eff. Addr. in 6-11 (MOVE) */
if (Dest.Mode == CCR) { /* MOVE to CCR */
Op = 0x44C0;
EffAdr (&Src, dea);
} else if (Dest.Mode == SR) { /* MOVE to SR */
Op = 0x46C0;
EffAdr (&Src, dea);
} else if (Src.Mode == SR) { /* MOVE from SR */
Op = 0x40C0;
EffAdr (&Dest, dea | aea);
} else if (Dest.Mode == USP) { /* MOVE to USP */
Op = 0x4E60;
if (Src.Mode == ARDir)
Op |= Src.Rn;
else
Error (SrcLoc, ModeErr);
} else if (Src.Mode == USP) { /* MOVE from USP */
Op = 0x4E68;
if (Dest.Mode == ARDir)
Op |= Dest.Rn;
else
Error (DestLoc, ModeErr);
} else { /* General MOVE instruction */
EffAdr (&Src, (ea | xxx));
if ((Size == Byte) && (Src.Mode == ARDir))
Error (SrcLoc, SizeErr);
if (Src.Mode > 12)
Error (SrcLoc, ModeErr);
if (((1<<(Dest.Mode-1)) IN (dea|aea)) || (Dest.Mode>12))
Error (DestLoc, ModeErr);
else if (Dest.Mode < 8) /* Register direct or indirect */
Op |= ((Dest.Mode - 1) << 6) | (Dest.Rn << 9);
else /* Absolute, PC relative, or immediate */
Op |= 0x01C0 | ((Dest.Mode - 8) << 9);
OperExt (&Dest); /* Set up extension word */
}
}
if ((Dest.Mode == CCR) && (Src.Mode == Imm)) {
if ((Size67 IN AdrModeB)
&& (EA05e IN AdrModeB)
&& (Exten IN AdrModeB))
if (0x0400 IN Op) /* not ANDI/EORI/ORI */
Error (DestLoc, ModeErr);
else
Op = (Op & 0xFF00) | 0x003C;
}
if ((Dest.Mode == SR) && (Src.Mode == Imm)) {
if ((Size67 IN AdrModeB)
&& (EA05e IN AdrModeB)
&& (Exten IN AdrModeB))
if (0x0400 IN Op) /* not ANDI/EORI/ORI */
Error (DestLoc, ModeErr);
else
Op = (Op & 0xFF00) | 0x007C;
}
}
ObjOp = Op;
InstSize += 2;
nO += 2;
if (nO > 2) {
templong = ExtL; /* Add extension word */
ObjOp = (ObjOp << 16) | (templong & 0x0000FFFFL);
}
if ((AdrModeA != 0) || (AdrModeB != 0)) {
InstSize += (nS = GetInstModeSize (Src.Mode));
ObjSrc = Src.Value;
InstSize += (nD = GetInstModeSize (Dest.Mode));
ObjDest = Dest.Value;
}
if (quick) {
InstSize -= nS; /* Source operand is in Op */
nS = 0;
}
if (Pass2) {
if ((nS!=0) && (Src.Hunk!=ABSHUNK)) { /* SrcOp relocatable */
if ((Src.Mode == AbsL)
|| (Src.Mode == AbsW)
|| (Src.Mode == ARDisp)
|| (Src.Mode == PCDisp)
|| (Src.Mode == Imm)) {
templong = AddrCnt+nO; /* 32- or 16-bit relocatable */
PutRel (templong, Src.Hunk, nS);
}
if ((Src.Mode==ARDisX) || (Src.Mode==PCDisX)) {
templong = AddrCnt + nO + 1; /* 8-bit relocatable */
PutRel (templong, Src.Hunk, 1);
}
}
if ((nD!=0) && (Dest.Hunk!=ABSHUNK)) { /* DestOp relocatable */
if ((Dest.Mode == AbsL)
|| (Dest.Mode == AbsW)
|| (Dest.Mode == ARDisp)
|| (Dest.Mode == PCDisp)
|| (Dest.Mode == Imm)) {
templong = AddrCnt+nO+nS; /* 32- or 16-bit relocatable */
PutRel (templong, Dest.Hunk, nD);
}
if ((Dest.Mode==ARDisX) || (Dest.Mode==PCDisX)) {
templong = AddrCnt+nO+nS+1; /* 8-bit relocatable */
PutRel (templong, Dest.Hunk, 1);
}
}
}
AddrAdv = InstSize;
}
SHAR_EOF
cat << \SHAR_EOF > Opcodes.c
/*------------------------------------------------------------------*/
/* */
/* MC68000 Cross Assembler */
/* */
/* Copyright (c) 1985 by Brian R. Anderson */
/* */
/* Opcode table and scan routine - January 6, 1989 */
/* */
/* This program may be copied for personal, non-commercial use */
/* only, provided that the above copyright notice is included */
/* on all copies of the source code. Copying for any other use */
/* without the consent of the author is prohibited. */
/* */
/*------------------------------------------------------------------*/
/* */
/* Originally published (in Modula-2) in */
/* Dr. Dobb's Journal, April, May, and June 1986. */
/* */
/* AmigaDOS conversion copyright 1989 by Charlie Gibbs. */
/* */
/*------------------------------------------------------------------*/
#include <stdio.h>
#include "a68kdef.h"
#include "a68kglb.h"
/* Functions */
extern int LineParts(), ObjDir();
extern int GetInstModeSize(), GetMultReg(), CountNest();
extern int ReadSymTab(), GetArgs(), GetAReg(), OpenIncl();
extern long AddrBndW(), AddrBndL(), GetValue(), CalcValue();
extern char *AddName(), *GetField();
extern struct SymTab *NextSym();
extern struct SymTab **HashIt();
int Instructions (loc) int loc;
/* Looks up opcode and addressing mode bit patterns
If the opcode corresponds to an executable instruction,
returns TRUE with the following fields set up:
Op - operation code bits
AdrModeA - addressing mode bits
AdrModeB - more addressing mode bits
Dir - None
If the opcode corresponds to a directive (AdrModeA in the table
is 0xFFFF), returns TRUE with the following fields set up:
Op - 0
AdrModeA - 0
AdrModeB - 0
Dir - the appropriate directive value
If not found, returns FALSE with all the above fields set to zero.
NOTE: The binary search doesn't use strcmp because this function
returns incorrect values under MS-DOS Lattice 2.12. */
{
static int maxinst = 0; /* Size of opcode table */
static int limits['Z'-'A'+2]; /* Table limits by first letter */
register char *i, *j;
register int lower, upper, mid; /* Binary search controls */
/* Opcode table */
struct OpTab {
char Mnem[8]; /* Instruction mnemonic */
int OpBits; /* Op code bits */
int AMA; /* Address mode bits */
int AMB; /* More address mode bits */
};
static struct OpTab MnemTab[] = {
"=", 0, 0xFFFF, Equ,
"ABCD", 0xC100, Rx911 | RegMem3 | Ry02, 0,
"ADD", 0xD000, OpM68D, EA05y,
"ADDA", 0xD000, OpM68A, EA05a,
"ADDI", 0x0600, 0, Size67 | EA05e | Exten,
"ADDQ", 0x5000, Data911, Size67 | EA05d,
"ADDX", 0xD100, Rx911 | RegMem3 | Ry02, Size67,
"AND", 0xC000, OpM68D, EA05x,
"ANDI", 0x0200, 0, Size67 | EA05e | Exten,
"ASL", 0xE100, CntR911, 0,
"ASR", 0xE000, CntR911, 0,
"BCC", 0x6400, Brnch, 0,
"BCHG", 0x0040, 0, EA05e | Exten | Bit811,
"BCLR", 0x0080, 0, EA05e | Exten | Bit811,
"BCS", 0x6500, Brnch, 0,
"BEQ", 0x6700, Brnch, 0,
"BGE", 0x6C00, Brnch, 0,
"BGT", 0x6E00, Brnch, 0,
"BHI", 0x6200, Brnch, 0,
"BLE", 0x6F00, Brnch, 0,
"BLS", 0x6300, Brnch, 0,
"BLT", 0x6D00, Brnch, 0,
"BMI", 0x6B00, Brnch, 0,
"BNE", 0x6600, Brnch, 0,
"BPL", 0x6A00, Brnch, 0,
"BRA", 0x6000, Brnch, 0,
"BSET", 0x00C0, 0, EA05e | Exten | Bit811,
"BSR", 0x6100, Brnch, 0,
"BSS", 0, 0xFFFF, BSS,
"BTST", 0x0000, 0, EA05c | Exten | Bit811,
"BVC", 0x6800, Brnch, 0,
"BVS", 0x6900, Brnch, 0,
"CHK", 0x4180, Rx911, EA05b,
"CLR", 0x4200, 0, Size67 | EA05e,
"CMP", 0xB000, OpM68C, EA05a,
"CMPA", 0xB000, OpM68A, EA05a,
"CMPI", 0x0C00, 0, Size67 | EA05e | Exten,
"CMPM", 0xB108, Rx911 | Ry02, Size67,
"CNOP", 0, 0xFFFF, Cnop,
"CODE", 0, 0xFFFF, CSeg,
"CSEG", 0, 0xFFFF, CSeg,
"DATA", 0, 0xFFFF, DSeg,
"DBCC", 0x54C8, DecBr, 0,
"DBCS", 0x55C8, DecBr, 0,
"DBEQ", 0x57C8, DecBr, 0,
"DBF", 0x51C8, DecBr, 0,
"DBGE", 0x5CC8, DecBr, 0,
"DBGT", 0x5EC8, DecBr, 0,
"DBHI", 0x52C8, DecBr, 0,
"DBLE", 0x5FC8, DecBr, 0,
"DBLS", 0x53C8, DecBr, 0,
"DBLT", 0x5DC8, DecBr, 0,
"DBMI", 0x5BC8, DecBr, 0,
"DBNE", 0x56C8, DecBr, 0,
"DBPL", 0x5AC8, DecBr, 0,
"DBRA", 0x51C8, DecBr, 0,
"DBT", 0x50C8, DecBr, 0,
"DBVC", 0x58C8, DecBr, 0,
"DBVS", 0x59C8, DecBr, 0,
"DC", 0, 0xFFFF, DC,
"DCB", 0, 0xFFFF, DCB,
"DIVS", 0x81C0, Rx911, EA05b,
"DIVU", 0x80C0, Rx911, EA05b,
"DS", 0, 0xFFFF, DS,
"DSEG", 0, 0xFFFF, DSeg,
"END", 0, 0xFFFF, End,
"ENDC", 0, 0xFFFF, EndC,
"ENDIF", 0, 0xFFFF, EndC,
"EOR", 0xB000, OpM68X, EA05e,
"EORI", 0x0A00, 0, Size67 | EA05e | Exten,
"EQU", 0, 0xFFFF, Equ,
"EQUR", 0, 0xFFFF, Equr,
"EVEN", 0, 0xFFFF, Even,
"EXG", 0xC100, OpM37, 0,
"EXT", 0x4800, OpM68S, 0,
"FAR", 0, 0xFFFF, Far,
"IDNT", 0, 0xFFFF, Idnt,
"IFC", 0, 0xFFFF, IfC,
"IFD", 0, 0xFFFF, IfD,
"IFEQ", 0, 0xFFFF, IfEQ,
"IFGE", 0, 0xFFFF, IfGE,
"IFGT", 0, 0xFFFF, IfGT,
"IFLE", 0, 0xFFFF, IfLE,
"IFLT", 0, 0xFFFF, IfLT,
"IFNC", 0, 0xFFFF, IfNC,
"IFND", 0, 0xFFFF, IfND,
"IFNE", 0, 0xFFFF, IfNE,
"ILLEGAL", 0x4AFC, 0, 0,
"INCLUDE", 0, 0xFFFF, Include,
"JMP", 0x4EC0, 0, EA05f,
"JSR", 0x4E80, 0, EA05f,
"LEA", 0x41C0, Rx911, EA05f,
"LINK", 0x4E50, Ry02, Exten,
"LIST", 0, 0xFFFF, DoList,
"LSL", 0xE308, CntR911, 0,
"LSR", 0xE208, CntR911, 0,
"MACRO", 0, 0xFFFF, Macro,
"MOVE", 0x0000, 0, Sz1213A | EA611,
"MOVEA", 0x0040, Rx911, Sz1213 | EA05a,
"MOVEM", 0x4880, 0, Size6 | EA05z | Exten,
"MOVEP", 0x0008, OpM68R, Exten,
"MOVEQ", 0x7000, Data07, 0,
"MULS", 0xC1C0, Rx911, EA05b,
"MULU", 0xC0C0, Rx911, EA05b,
"NBCD", 0x4800, 0, EA05e,
"NEAR", 0, 0xFFFF, Near,
"NEG", 0x4400, 0, Size67 | EA05e,
"NEGX", 0x4000, 0, Size67 | EA05e,
"NOL", 0, 0xFFFF, NoList,
"NOLIST",0, 0xFFFF, NoList,
"NOP", 0x4E71, 0, 0,
"NOT", 0x4600, 0, Size67 | EA05e,
"OR", 0x8000, OpM68D, EA05x,
"ORG", 0, 0xFFFF, Org,
"ORI", 0x0000, 0, Size67 | EA05e | Exten,
"PAGE", 0, 0xFFFF, Page,
"PEA", 0x4840, 0, EA05f,
"PUBLIC",0, 0xFFFF, Public,
"REG", 0, 0xFFFF, Reg,
"RESET", 0x4E70, 0, 0,
"ROL", 0xE718, CntR911, 0,
"ROR", 0xE618, CntR911, 0,
"RORG", 0, 0xFFFF, Org,
"ROXL", 0xE510, CntR911, 0,
"ROXR", 0xE410, CntR911, 0,
"RTE", 0x4E73, 0, 0,
"RTR", 0x4E77, 0, 0,
"RTS", 0x4E75, 0, 0,
"SBCD", 0x8100, Rx911 | RegMem3 | Ry02, 0,
"SCC", 0x54C0, 0, EA05e,
"SCS", 0x55C0, 0, EA05e,
"SECTION", 0, 0xFFFF, Section,
"SEQ", 0x57C0, 0, EA05e,
"SET", 0, 0xFFFF, Set,
"SF", 0x51C0, 0, EA05e,
"SGE", 0x5CC0, 0, EA05e,
"SGT", 0x5EC0, 0, EA05e,
"SHI", 0x52C0, 0, EA05e,
"SLE", 0x5FC0, 0, EA05e,
"SLS", 0x53C0, 0, EA05e,
"SLT", 0x5DC0, 0, EA05e,
"SMI", 0x5BC0, 0, EA05e,
"SNE", 0x56C0, 0, EA05e,
"SPC", 0, 0xFFFF, Space,
"SPL", 0x5AC0, 0, EA05e,
"ST", 0x50C0, 0, EA05e,
"STOP", 0x4E72, 0, Exten,
"SUB", 0x9000, OpM68D, EA05y,
"SUBA", 0x9000, OpM68A, EA05a,
"SUBI", 0x0400, 0, Size67 | EA05e | Exten,
"SUBQ", 0x5100, Data911, Size67 | EA05d,
"SUBX", 0x9100, Rx911 | RegMem3 | Ry02, Size67,
"SVC", 0x58C0, 0, EA05e,
"SVS", 0x59C0, 0, EA05e,
"SWAP", 0x4840, Ry02, 0,
"TAS", 0x4AC0, 0, EA05e,
"TITLE", 0, 0xFFFF, Title,
"TRAP", 0x4E40, Data03, 0,
"TRAPV", 0x4E76, 0, 0,
"TST", 0x4A00, 0, Size67 | EA05e,
"UNLK", 0x4E58, Ry02, 0,
"XDEF", 0, 0xFFFF, Xdef,
"XREF", 0, 0xFFFF, Xref,
"",0,0,0}; /* End-of-table flag */
if (maxinst == 0) { /* Determine size of opcode table */
while (MnemTab[maxinst].Mnem[0])
maxinst++;
limits[0] = 0;
limits['Z'-'A'+1] = maxinst;
mid = 0;
for (lower = 0; lower < maxinst; lower++) {
upper = (unsigned int) MnemTab[lower].Mnem[0] - 'A' + 1;
if (upper != mid) {
if (upper > 0) { /* Start of the next letter */
mid++;
while (mid < upper)
limits[mid++] = lower;
limits[mid] = lower;
}
}
}
mid++;
while (mid < 'Z'-'A'+1) {
limits[mid++] = maxinst; /* In case we didn't get to Z */
}
}
mid = (unsigned int) OpCode[0] - 'A' + 1;
if (mid < 0) { /* This catches stuff like "=" */
lower = 0;
upper = limits[1];
} else if (mid > 'Z'-'A'+1) {
lower = upper = 0; /* Reject this one */
} else {
lower = limits[mid++];
upper = limits[mid];
}
while (lower < upper) {
mid = (lower + upper) / 2; /* Search opcode table */
for (i = OpCode, j = MnemTab[mid].Mnem; *i == *j; i++, j++)
if (*i == '\0')
break; /* Find first non-match */
if (*i < *j)
upper = mid; /* Search lower half of table */
else if (*i > *j)
lower = mid + 1; /* Search upper half of table */
else if (MnemTab[mid].AMA != 0xFFFF) { /* Found it */
Op = MnemTab[mid].OpBits; /* Executable instruction */
AdrModeA = MnemTab[mid].AMA;
AdrModeB = MnemTab[mid].AMB;
Dir = None;
return (TRUE);
} else {
Op = AdrModeA = AdrModeB = 0; /* Directive */
Dir = MnemTab[mid].AMB;
return (TRUE);
}
}
Op = AdrModeA = AdrModeB = Dir = 0;
return (FALSE); /* Didn't find it */
}
SHAR_EOF
# End of shell archive
exit 0
--
Bob Page, U of Lowell CS Dept. page@swan.ulowell.edu ulowell!page
Have five nice days.